package com.meirengu.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 全局状态码常量类
 *
 * @author Marvin
 * @create 2017-02-09 下午3:22
 */
public class RedisClient {


    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private JedisPool jedisPool;

    public RedisClient(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }


    public boolean exists(String key) {
        Boolean exist = false;
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            exist = jedis.exists(key);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close(); //注意这里不是关闭连接，在JedisPool模式下，Jedis会被归还给资源池。
        }
        return exist;
    }

    public String get(String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.get(key);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;
    }


    public void set(String key, String value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.set(key, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
    }

    public void set(String key, String value, int seconds) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.setex(key, seconds, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
    }

    /**
     * 将 key 中储存的数字值增一
     *
     * @param key
     * @return
     */
    public Long incr(String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.incr(key);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;
    }

    /**
     * 将 key 中储存的数字值增一并设置过期时间
     *
     * @param key
     * @param seconds
     */
    public Long incr(String key, int seconds) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            Long num = jedis.incr(key);
            jedis.expire(key, seconds);
            return num;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;

    }

    public long expire(String key, int seconds) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.expire(key, seconds);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return 0;
    }

    /**
     * 指定key在某个时间过期
     *
     * @param seconds 距1970年的秒数
     * @return
     */
    public long expireAt(String key, long seconds) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.expireAt(key, seconds);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return 0;
    }

    public long remove(String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.del(key);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return 0;
    }



    /*SET集合*/


    public void sadd(String key, String value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.sadd(key, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
    }

    /**
     * 求差集
     *
     * @param key1
     * @param key2
     * @return
     */
    public Set<String> sdiff(String key1, String key2) {
        Jedis jedis = null;
        Set<String> set = new HashSet<>();
        try {
            jedis = jedisPool.getResource();
            set = jedis.sdiff(key1, key2);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return set;
    }


    /**
     * 求交集
     *
     * @param key1
     * @param key2
     * @return
     */
    public Set<String> sinter(String key1, String key2) {
        Jedis jedis = null;
        Set<String> set = new HashSet<>();
        try {
            jedis = jedisPool.getResource();
            set = jedis.sinter(key1, key2);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return set;
    }

    public void sadd(String key, Set<String> value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            for (String str : value) {
                jedis.sadd(key, str);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
    }


    public void srem(String key, String value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.srem(key, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
    }

    public Set<String> smembers(String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            Set<String> members = jedis.smembers(key);
            return members;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;
    }

    public boolean sismember(String key, String member) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            Boolean isMember = jedis.sismember(key, member);
            return isMember;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return false;
    }


    /*哈希Hash*/

    public void hset(String key, String field, String value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.hset(key, field, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }

    }

    public String hget(String key, String field) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.hget(key, field);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;
    }

    public Long hincrBy(String key, String field, long value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.hincrBy(key, field, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;
    }

    public Map<String, String> hgetAll(String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.hgetAll(key);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;
    }

    /*列表List*/

    public long lpush(String key, String[] valueArr) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.lpush(key, valueArr);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return 0;

    }

    public long lpush(String key, String value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.lpush(key, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return 0;

    }

    public long lpush(byte[] key, byte[] value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.lpush(key, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return 0;

    }

    public byte[] lindex(byte[] key, long index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.lindex(key, index);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;

    }

    public Long llen(byte[] key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.llen(key);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;

    }

    /**
     * 返回set元素数
     */
    public Long scard(String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.scard(key);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;
    }

    public List<String> blpop(int timout, String key) {
        /*Spring提供的计时器StopWatch对于秒、毫秒为单位方便计时的程序，
        尤其是单线程、顺序执行程序的时间特性的统计输出支持比较好。
        也就是说假如我们手里面有几个在顺序上前后执行的几个任务，
        而且我们比较关心几个任务分别执行的时间占用状况，
        希望能够形成一个不太复杂的日志输出，StopWatch提供了这样的功能。
        而且Spring的StopWatch基本上也就是仅仅为了这样的功能而实现。
        StopWatch watch = new StopWatch();
        watch.start();*/

        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            return jedis.blpop(1, key);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null)
                jedis.close();
        }
        return null;
    }

    public static void main(String[] args) throws InterruptedException {
        JedisPoolConfig config = new JedisPoolConfig();
        //最大空闲连接数, 应用自己评估，不要超过ApsaraDB for Redis每个实例最大的连接数
        config.setMaxIdle(200);
        //最大连接数, 应用自己评估，不要超过ApsaraDB for Redis每个实例最大的连接数
        config.setMaxTotal(300);
        config.setTestOnBorrow(false);
        config.setTestOnReturn(false);
        String host = "39.106.210.85";
        String password = "kwd2018";
        JedisPool pool = new JedisPool(config, host, 6379, 3000, password);
        RedisClient redisService = new RedisClient(pool);
        redisService.set("foo", "bar");
        String foobar = redisService.get("foo");
        redisService.sadd("sose", "car");
        redisService.sadd("sose", "bike");
        Map<String, String> sose = redisService.hgetAll("sose");
        pool.destroy();

    }

}
